package com.mazaiting.screen.video

import android.app.Service
import android.content.Intent
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.media.MediaRecorder
import android.media.projection.MediaProjection
import android.os.Binder
import android.os.HandlerThread
import android.os.IBinder
import android.os.Process
import android.util.Log
import com.mazaiting.screen.util.FileUtil
import com.mazaiting.screen.util.ScreenUtil
import java.io.IOException


/***
 *
 *
 *                                                    __----~~~~~~~~~~~------___
 *                                   .  .   ~~//====......          __--~ ~~
 *                   -.            \_|//     |||\\  ~~~~~~::::... /~
 *                ___-==_       _-~o~  \/    |||  \\            _/~~-
 *        __---~~~.==~||\=_    -_--~/_-~|-   |\\   \\        _/~
 *    _-~~     .=~    |  \\-_    '-~7  /-   /  ||    \      /
 *  .~       .~       |   \\ -_    /  /-   /   ||      \   /
 * /  ____  /         |     \\ ~-_/  /|- _/   .||       \ /
 * |~~    ~~|--~~~~--_ \     ~==-/   | \~--===~~        .\
 *          '         ~-|      /|    |-~\~~       __--~~
 *                      |-~~-_/ |    |   ~\_   _-~            /\
 *                           /  \     \__   \/~                \__
 *                       _--~ _/ | .-~~____--~-/                  ~~==.
 *                      ((->/~   '.|||' -_|    ~~-/ ,              . _||
 *                                 -_     ~\      ~~---l__i__i__i--~~_/
 *                                 _-~-__   ~)  \--______________--~~
 *                               //.-~~~-~_--~- |-------~~~~~~~~
 *                                      //.-~~~--\
 *                               神兽保佑
 *                              代码无BUG!
 * @author mazaiting
 * @date 2019-07-22
 * @description 视频服务
 */
class VideoService : Service() {

    companion object {
        /**
         * TAG
         */
        private const val TAG = "VideoService"
    }

    /**
     * 媒体工程
     */
    private var mMediaProjection: MediaProjection? = null
    /**
     * 媒体录音
     */
    private var mMediaRecorder: MediaRecorder? = null
    /**
     * 虚拟化显示
     */
    private var mVirtualDisplay: VirtualDisplay? = null
    /**
     * 标记是否正在运行
     */
    var isRunning: Boolean = false
        private set
    /**
     * 视频宽度
     */
    private var mWindowWidth = 720
    /**
     * 视频高度
     */
    private var mWindowHeight = 1080
    /**
     * 屏幕像素
     */
    private var mScreenDensity: Int = 0

    override fun onBind(intent: Intent): IBinder = VideoBinder()

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        return START_STICKY
    }

    override fun onCreate() {
        super.onCreate()
        // 后台线程启动
        val serviceThread = HandlerThread("service_thread", Process.THREAD_PRIORITY_BACKGROUND)
        serviceThread.start()
        // 标记未启动
        isRunning = false
        initDisplay()
        // 初始化
        mMediaRecorder = MediaRecorder()
    }

    /**
     * 初始化显示
     */
    private fun initDisplay() {
        // 获取屏幕宽高
        val display = ScreenUtil.getDisplay(this)
        mWindowWidth = display.x
        mWindowHeight = display.y
        // 获取屏幕 DPI
        mScreenDensity = ScreenUtil.getDensityDpi(this)
    }

    /**
     * 设置媒体工程
     * @param project 媒体工程
     */
    fun setMediaProject(project: MediaProjection) {
        this.mMediaProjection = project
    }

    /**
     * 开始录屏
     * @return true: 正在录制; false: 录制失败
     */
    fun startRecord(): Boolean {
        if (mMediaProjection == null || isRunning) {
            Log.i(TAG, "mMediaProjection is null, isRunning: $isRunning")
            return false
        }
        // 初始化记录者
        initRecorder()
        // 创建虚拟化显示
        createVirtualDisplay()
        // 开始录制
        mMediaRecorder?.start()
        // 标记正在录制
        isRunning = true
        return true
    }

    /**
     * 停止录频
     * @return true: 停止成功; false: 停止失败
     */
    fun stopRecord(): Boolean = stopRecord(null)

    /**
     * 停止录频
     * @param listener 视频监听
     * @return true: 停止成功; false: 停止失败
     */
    fun stopRecord(listener: IVideoListener?): Boolean {
        // 正在运行
        if (!isRunning) {
            return false
        }
        // 停止
        isRunning = false
        // 停止录制
        mMediaRecorder?.stop()
        // 重置
        mMediaRecorder?.reset()
        // 释放
        mVirtualDisplay!!.release()
        // 停止
        mMediaProjection!!.stop()
        // 清空
        mMediaProjection = null
        // 设置监听
        listener?.onVideo(getFilePath())
        return true
    }

    /**
     * 创建虚拟化显示
     */
    private fun createVirtualDisplay() {
        mVirtualDisplay = mMediaProjection!!.createVirtualDisplay(
            "MainScreen", mWindowWidth, mWindowHeight, mScreenDensity,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder?.surface, null, null
        )
    }

    /**
     * 初始化音频
     */
    private fun initRecorder() {
        // 设置声音源
        mMediaRecorder?.setAudioSource(MediaRecorder.AudioSource.MIC)
        // 设置视频源
        mMediaRecorder?.setVideoSource(MediaRecorder.VideoSource.SURFACE)
        // 设置输出格式
        mMediaRecorder?.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
        // 设置输出路径
        mMediaRecorder?.setOutputFile(getFilePath())
        // 设置视频大小
        mMediaRecorder?.setVideoSize(mWindowWidth, mWindowHeight)
        // 设置视频编码
        mMediaRecorder?.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
        // 设置音频编码
        mMediaRecorder?.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
        // 设置音频码率
        mMediaRecorder?.setVideoEncodingBitRate(5 * 1024 * 1024)
        // 设置视频帧率
        mMediaRecorder?.setVideoFrameRate(30)
        try {
            // 准备
            mMediaRecorder?.prepare()
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }

    override fun onDestroy() {
        mMediaProjection = null
        mMediaRecorder = null
        mVirtualDisplay = null
        super.onDestroy()
    }

    /**
     * 文件路径
     */
    private fun getFilePath(): String = "${FileUtil.getDir(this)}/${System.currentTimeMillis()}.mp4"

    /**
     * 视频服务绑定
     */
    inner class VideoBinder : Binder() {
        val service: VideoService
            get() = this@VideoService
    }

    /**
     * 视频监听
     */
    interface IVideoListener {
        /**
         * 视频
         * @param path 视频路径
         */
        fun onVideo(path: String)
    }
}